package com.smsc.headend.task.engine.executor.impl.firmware;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.SystemClock;
import cn.hutool.core.map.MapUtil;
import com.smsc.headend.common.enums.DeviceType;
import com.smsc.headend.common.enums.errorcode.TaskExecuteErrorCode;
import com.smsc.headend.common.utils.RedisUtils;
import com.smsc.headend.module.asset.dmo.ComConfigDMO;
import com.smsc.headend.module.asset.dmo.MeterConfigDMO;
import com.smsc.headend.module.asset.entity.ComEntity;
import com.smsc.headend.module.common.entity.DeviceOperation;
import com.smsc.headend.module.data.dmo.DeviceSAPandKeys;
import com.smsc.headend.module.data.dto.DataItemDTO;
import com.smsc.headend.module.data.enums.DictionaryType;
import com.smsc.headend.module.data.enums.OperationGroup;
import com.smsc.headend.module.fwu.entity.FirmwareFile;
import com.smsc.headend.module.fwu.entity.LogFwUpgradeHis;
import com.smsc.headend.module.fwu.entity.TemplateFwUpgrade;
import com.smsc.headend.module.task.dto.AtomicTask;
import com.smsc.headend.module.task.dto.Task;
import com.smsc.headend.task.engine.exception.UDISTaskExecutorException;
import com.smsc.headend.task.engine.executor.TaskExecutor;
import com.smsc.headend.task.engine.facade.DataItemFacade;
import com.smsc.headend.task.engine.handler.impl.firmware.UpgradeSettingsHandler;
import com.smsc.headend.task.engine.mapper.FirmwareFileMapper;
import com.smsc.headend.module.task.dto.AtomicTaskState;
import com.smsc.headend.task.engine.service.ConnectorService;
import com.smsc.headend.task.engine.service.FeignAssetManagementService;
import com.smsc.headend.task.engine.service.asset.AssetService;
import com.smsc.headend.task.engine.service.task.TaskPacketService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;

/**
 * @author xiaosc
 * @date 2020/11/25
 */
@Slf4j
public class UpgradeSettingsExecutor implements TaskExecutor {
    @Autowired
    TaskPacketService packetService;
    @Autowired
    ConnectorService connectorService;
    @Autowired
    RedisUtils redisUtils;
    @Autowired
    FeignAssetManagementService assetManagementRemoteService;
    @Autowired
    DataItemFacade dataItemFacade;
    @Autowired
    FirmwareFileMapper firmwareFileMapper;
    @Autowired
    AssetService assetService;

    @Override
    public AtomicTaskState execute(Task task, AtomicTask atomicTask) throws UDISTaskExecutorException {
        log.info("execute step upgrade setting");
        DeviceOperation dictionary = assetService.getDictionary(atomicTask.getOperationId(), DictionaryType.Operation.getType());
        Map<String, Object> paramMap = this.getParameterMap(task, atomicTask);

        Map<String, Object> upgradeSettingsParams = MapUtil.newHashMap();
        FirmwareFile firmwareFile = firmwareFileMapper.selectById(MapUtil.getLong(paramMap, "fwFileId"));
        if (firmwareFile == null) {
            throw new UDISTaskExecutorException(TaskExecuteErrorCode.FW_FILE_NOT_EXISTS.toString());
        }
        upgradeSettingsParams.put("fileName", firmwareFile.getFwFileName());
        upgradeSettingsParams.put("imageIdentifier", firmwareFile.getFwFileIdentifier());
        upgradeSettingsParams.put("imageSize", firmwareFile.getFwFileSize());
        upgradeSettingsParams.put("activeTime", paramMap.get("activeTime"));
        upgradeSettingsParams.put("meterIds", paramMap.get("meterIds"));
        upgradeSettingsParams.put("fwFileTypeId",  firmwareFile.getFwFileTypeId());
        if (paramMap.containsKey("transferType")) {
            upgradeSettingsParams.put("transferType", paramMap.get("transferType"));
        }

        ComEntity terminal = assetService.getComById(task.getComId());
        ComConfigDMO comConfigDMO = assetService.getComConfigById(task.getComId());
        String interfaceType = comConfigDMO.getInterfaceType();
        Boolean isShortName = comConfigDMO.getIsShortName();
        MeterConfigDMO meterConfigDMO = null;
        if (task.getMeterId() != null) {
            meterConfigDMO = assetService.getMeterConfigById(task.getMeterId());
            interfaceType = meterConfigDMO.getInterfaceType();
            isShortName = meterConfigDMO.getIsShortName();
        }
        List<DataItemDTO> dataItemDTOList = dataItemFacade.getDataItemsByOperation(null, terminal, dictionary, getParameterMap(task, atomicTask), comConfigDMO.getModelId());
        if (CollectionUtils.isEmpty(dataItemDTOList)) {
            throw new UDISTaskExecutorException(TaskExecuteErrorCode.DATAITEM_NOT_EXISTS.toString());
        }
        DeviceSAPandKeys deviceKeys =
                assetManagementRemoteService.getTerminalCommunicationKey(terminal.getComId(), dataItemDTOList.get(0).getRoleId());
        byte[] packets = packetService.upgradeSettings(comConfigDMO.getModelId(), dataItemDTOList.get(0), atomicTask, upgradeSettingsParams, interfaceType, isShortName, deviceKeys.getWPort().intValue());
        connectorService.sendPacket(task, atomicTask, dataItemDTOList.get(0).getRoleId(), true, packets);
        return createAtomicState(UpgradeSettingsHandler.class);
    }

    @Override
    public Boolean handleFailure(Task task, AtomicTask atomicTask, String message) {
        log.info("error {}, ", message);
        if (atomicTask.getGroupId() == OperationGroup.DCUFtpSettings.getId().intValue()
                || atomicTask.getGroupId() == OperationGroup.MeterFtpSettings.getId().intValue()
                || atomicTask.getGroupId() == OperationGroup.MModUpgradeSettings.getId().intValue()
                || atomicTask.getGroupId() == OperationGroup.SModUpgradeSettings.getId().intValue()) {
            Map<String, Object> parameterMap = getParameterMap(task, atomicTask);
            Long taskId = MapUtil.getLong(parameterMap, "taskId");
            Long tvEnd = SystemClock.now() / 1000;
            if (atomicTask.getGroupId() == OperationGroup.DCUFtpSettings.getId().intValue() || atomicTask.getGroupId() == OperationGroup.MModUpgradeSettings.getId().intValue()) {
                ComEntity com = assetService.getComById(task.getComId());
                if (com != null) {
                    assetManagementRemoteService.saveFwuReport(com.getDeviceId(), DeviceType.DCU.getId(), null, taskId, TemplateFwUpgrade.TaskType.FtpSettings.getCode(), LogFwUpgradeHis.UpgradeResult.failed.getCode(), null, tvEnd, message);
                }
            } else {
                String meterIdsStr = MapUtil.getStr(parameterMap, "meterIds");
                String[] meterIds = meterIdsStr.split(",");
                for (String meterId : meterIds) {
                    assetManagementRemoteService.saveFwuReport(Convert.toLong(meterId), DeviceType.METER.getId(), null, taskId, TemplateFwUpgrade.TaskType.FtpSettings.getCode(), LogFwUpgradeHis.UpgradeResult.failed.getCode(), null, tvEnd, message);
                }
            }
        }
        return true;
    }
}
